﻿using JBeamLibrary;
using JBeamLibrary.Types;
using JBeamLibrary.VehicleParts.Collections;
using JBeamLibrary.VehicleParts.Elements;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace DriveBeamEditor.Wpf
{
    public static class WpfHelper
    {
        public static Point3D ToPoint3D(this Float3 offset, double scale = 10.0)
        {
            return new Point3D(offset.X * scale, offset.Y * scale, offset.Z * scale);
        }

        public static Float3 ToFloat3(this Point3D offset, double scale = 10.0)
        {
            return new Float3(
                (float)Math.Round(offset.X / scale, 3),
                (float)Math.Round(offset.Y / scale, 3),
                (float)Math.Round(offset.Z / scale, 3));
        }

        public static Point3D ToPoint3D(this Node node, double scale = 10.0)
        {
            return new Point3D(node.PosX * scale, node.PosY * scale, node.PosZ * scale);
        }

        public static void ToPoints(this Beam beam, Vehicle vehicle, out Point3D? start, out Point3D? end, double scale = 10.0)
        {
            Node startNode;
            Node endNode;
            beam.GetNodes(vehicle, out startNode, out endNode);

            start = null;
            end = null;

            if (startNode != null)
                start = startNode.ToPoint3D(scale);
            if (endNode != null)
                end = endNode.ToPoint3D(scale);
        }

        public static void ToPoints(this Thruster thruster, Vehicle vehicle, out Point3D? start, out Point3D? end, double scale = 10.0)
        {
            Node startNode;
            Node endNode;
            thruster.GetNodes(vehicle, out startNode, out endNode);

            start = null;
            end = null;

            if (startNode != null)
                start = startNode.ToPoint3D(scale);
            if (endNode != null)
                end = endNode.ToPoint3D(scale);
        }

        public static Tuple<Point3D, Point3D, Point3D, Point3D, Point3D, Point3D> ToPoints(
            this InternalCamera camera, Vehicle vehicle, out Point3D? origin, double scale = 10.0)
        {
            origin = camera.Offset.ToPoint3D(scale);

            Node node1, node2, node3, node4, node5, node6;
            camera.GetNodes(vehicle, out node1, out node2, out node3, out node4, out node5, out node6);
            return new Tuple<Point3D, Point3D, Point3D, Point3D, Point3D, Point3D>(
                node1.ToPoint3D(scale), node2.ToPoint3D(scale), node3.ToPoint3D(scale), node4.ToPoint3D(scale), node5.ToPoint3D(scale), node6.ToPoint3D(scale));
        }

        public static IEnumerable<Point3D> ToPoints(this NodeCollection nodes, double scale = 10.0)
        {
            return nodes.Select(node => node.ToPoint3D(scale));
        }

        public static IEnumerable<Point3D> ToPoints(this BeamCollection beams, Vehicle vehicle, double scale = 10.0)
        {
            var nodePoints = new List<Point3D>();
            foreach (var beam in beams)
            {
                Point3D? start;
                Point3D? end;
                beam.ToPoints(vehicle, out start, out end, scale);

                if (!start.HasValue || !end.HasValue) continue;

                nodePoints.Add(start.Value);
                nodePoints.Add(end.Value);
            }

            return nodePoints.AsEnumerable();
        }

        public static IEnumerable<Point3D> ToPoints(this ThrusterCollection thrusters, Vehicle vehicle, double scale = 10.0)
        {
            var nodePoints = new List<Point3D>();
            foreach (var thruster in thrusters)
            {
                Point3D? start;
                Point3D? end;
                thruster.ToPoints(vehicle, out start, out end, scale);

                if (!start.HasValue || !end.HasValue) continue;

                nodePoints.Add(start.Value);
                nodePoints.Add(end.Value);
            }

            return nodePoints.AsEnumerable();
        }
    }
}
